文章背景与核心概要
在构建现代机器学习应用时,开发者常常面临两难境地:一方面希望利用 Gradio 强大的后端基础设施(如请求队列、并发控制、SSE 流式传输以及 Hugging Face Spaces 上的 ZeroGPU 支持),另一方面又需要使用 React、Svelte 或原生 HTML/JS 构建高度定制化的复杂前端界面。传统的 Gradio 虽然开发便捷,但在极致的 UI 自定义方面存在局限。
本文介绍了全新的 gradio.Server,它扩展了 FastAPI 框架,无缝融合了 Gradio 的核心后端能力。通过 @app.api() 装饰器,开发者可以在享受零配置托管、GPU 资源动态分配以及客户端兼容性的同时,自由编写完全定制的前端页面。这使得 Gradio 不再局限于内置的 UI 组件,而是正式转型为一个功能完备的高性能后端框架。
gradio.Server: Any Custom Frontend with Gradio's Backend
Published on April 1, 2026 by yuvraj sharma and Abubakar Abid
Published on April 1, 2026 by yuvraj sharma and Abubakar Abid
📌 Summary
gradio.Server bridges the gap between custom web development and powerful machine learning backends. It extends FastAPI while incorporating Gradio's robust queuing engine, concurrency control, SSE streaming, and ZeroGPU support on Hugging Face Spaces. This allows developers to build rich, tailored frontends using frameworks like React, Svelte, or vanilla HTML/JS, without sacrificing Gradio's backend infrastructure or client compatibility.
gradio.Server弥合了自定义 Web 开发与强大的机器学习后端之间的鸿沟。它扩展了 FastAPI,同时融合了 Gradio 强大的队列引擎、并发控制、SSE 流式传输以及 Hugging Face Spaces 上的 ZeroGPU 支持。这使得开发者能够使用 React、Svelte 或原生 HTML/JS 等框架构建丰富、定制化的前端,而无需放弃 Gradio 的后端基础设施或客户端兼容性。
What We Wanted to Build
我们想要构建什么
Text Behind Image is an interactive editor where you upload a photo, remove its background using an ML model, and place stylized text between the foreground subject and the background.
Text Behind Image 是一个交互式编辑器,你可以在其中上传照片,利用机器学习模型去除背景,并将带有风格化的文本放置在前景主体与背景之间。
This project requires: * A drag-and-drop canvas with layered rendering (background → text → foreground). * A control panel with fine-tuned parameters for typography, color, opacity, shadows, and 3D perspective transforms. * A backend ML endpoint to perform background removal and return a transparent PNG. * Client-side export to PNG.
该项目需要满足以下要求: * 带有图层渲染(背景 → 文本 → 前景)的拖拽画布。 * 包含排版、颜色、不透明度、阴影和 3D 透视变换微调参数的控制面板。 * 用于执行背景去除并返回透明 PNG 的后端机器学习端点。 * 客户端导出为 PNG 功能。
While these complex requirements go beyond native Gradio components, developers still want Gradio's infrastructure advantages—such as queuing, concurrency management, ZeroGPU support, and zero-headache hosting on HF Spaces.
尽管这些复杂的需求超出了原生 Gradio 组件的能力范围,但开发者仍然希望获得 Gradio 的基础设施优势——例如队列管理、并发控制、ZeroGPU 支持以及在 HF Spaces 上轻松无忧的托管体验。
Enter gradio.Server
隆重介绍
gradio.Server
gradio.Server extends FastAPI to give you custom routes, middleware, and flexible responses alongside Gradio's API engine.
gradio.Server扩展了 FastAPI,在提供 Gradio API 引擎的同时,赋予你自定义路由、中间件以及灵活响应的能力。
Here is the complete Python backend for the Text Behind Image app:
以下是“文字置于图后(Text Behind Image)”应用的完整 Python 后端代码:
import os
import torch
from PIL import Image
from torchvision import transforms
from transformers import AutoModelForImageSegmentation
from gradio import Server
from gradio.data_classes import FileData
from fastapi.responses import HTMLResponse
import spaces
torch.set_float32_matmul_precision("high")
birefnet = AutoModelForImageSegmentation.from_pretrained(
"ZhengPeng7/BiRefNet", trust_remote_code=True
)
birefnet.to("cuda")
birefnet.float()
transform_image = transforms.Compose([
transforms.Resize((1024, 1024)),
transforms.ToTensor(),
transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225]),
])
app = Server()
@spaces.GPU
def segment(image: Image.Image) -> Image.Image:
"""Run BiRefNet segmentation to produce a transparency mask."""
image_size = image.size
input_images = transform_image(image).unsqueeze(0).to("cuda")
with torch.no_grad():
preds = birefnet(input_images)[-1].sigmoid().cpu()
pred = preds[0].squeeze()
mask = transforms.ToPILImage()(pred).resize(image_size)
image.putalpha(mask)
return image
@app.api(name="remove_background")
def remove_background(image_path: FileData) -> FileData:
"""Remove background from an image. Returns transparent PNG."""
im = Image.open(image_path["path"]).convert("RGB")
result = segment(im)
out_path = image_path["path"].rsplit(".", 1)[0] + ".png"
result.save(out_path)
return FileData(path=out_path)
@app.get("/", response_class=HTMLResponse)
async def homepage():
html_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), "index.html")
with open(html_path, "r", encoding="utf-8") as f:
return f.read()
app.launch(show_error=True)
In roughly 50 lines of code, the model loads at startup, @spaces.GPU handles ZeroGPU allocation, and gradio.Server manages queuing and concurrency.
在大约 50 行代码中,模型在启动时加载,
@spaces.GPU负责处理 ZeroGPU 分配,而gradio.Server则管理队列和并发。
Why @app.api() Instead of a Plain FastAPI Route?
为什么选择
@app.api()而不是普通的 FastAPI 路由?
Standard FastAPI background removal endpoints can easily crash or return corrupted data when multiple users hit them simultaneously without concurrency management.
如果没有并发管理,当多个用户同时访问时,标准的 FastAPI 背景去除端点很容易崩溃或返回损坏的数据。
@app.api() wraps your functions inside Gradio's queuing engine:
* Requests are neatly serialized and concurrency is controlled.
* GPU allocation on ZeroGPU Spaces is handled via @spaces.GPU.
* Endpoints become fully compatible with gradio_client:
@app.api()将你的函数包装在 Gradio 的队列引擎中: * 请求被整齐地序列化,并发得到有效控制。 * ZeroGPU Spaces 上的 GPU 分配通过@spaces.GPU处理。 * 端点与gradio_client完全兼容:
from gradio_client import Client, handle_file
client = Client("ysharma/text-behind-image")
result = client.predict(
image_path=handle_file("photo.jpg"),
api_name="/remove_background"
)
Meanwhile, standard FastAPI routes like @app.get("/") coexist naturally to serve custom static assets or HTML pages.
同时,像
@app.get("/")这样的标准 FastAPI 路由可以自然共存,用于提供自定义静态资源或 HTML 页面。
The Frontend: Pure HTML/CSS/JS
前端:纯 HTML/CSS/JS
The frontend communicates with the backend using the Gradio JS Client:
前端通过 Gradio JS 客户端 与后端进行通信:
import { Client, handle_file } from "https://cdn.jsdelivr.net/npm/@gradio/client/dist/index.min.js";
const client = await Client.connect(window.location.origin);
const result = await client.predict("/remove_background", {
image_path: handle_file(file),
});
foregroundLayer.src = result.data[0].url; // transparent PNG
By routing requests through the Gradio JS client rather than raw fetch() calls, the frontend integrates with Gradio's queue to manage concurrency, prevent GPU collisions, and display queue status.
通过 Gradio JS 客户端(而不是原始的
fetch()调用)路由请求,前端能够与 Gradio 的队列集成,从而管理并发、防止 GPU 冲突并显示队列状态。
What This Unlocks
这带来了哪些突破
Before gradio.Server |
After gradio.Server |
|---|---|
| Custom UI meant leaving Gradio entirely | Custom UI with Gradio's backend engine |
| No way to serve static HTML natively from a Gradio app | @app.get("/") serves anything effortlessly |
gradio_client only worked with Gradio component apps |
@app.api() endpoints are fully client-compatible |
| Forced choice between infrastructure control and design freedom | You get both |
引入 gradio.Server之前引入 gradio.Server之后自定义 UI 意味着必须完全放弃 Gradio 拥有 Gradio 后端引擎的自定义 UI 以及 完整控制权 无法从 Gradio 应用中原生提供静态 HTML 服务 @app.get("/")可以轻松托管任何内容gradio_client仅适用于 Gradio 组件应用@app.api()端点与客户端完全兼容在基础设施控制权与设计自由度之间被迫二选一 二者兼得
With gradio.Server, Gradio doubles as a backend framework: use its native UI components when you want them, or bring your own custom frontend when you don't.
借助
gradio.Server,Gradio 摇身一变成为双重身份的后端框架:当你需要时可以使用其原生 UI 组件,而当你不需要时则可以带来你自己的自定义前端。
Try It Out
立即体验
Explore the live Space: ysharma/text-behind-image
探索在线 Space:ysharma/text-behind-image
What's Next
下一步计划
This post highlights the core capabilities of pairing custom frontends with Gradio's backend via gradio.Server. Future updates will dive into MCP tool registration using @app.mcp.tool(), SSE streaming for real-time updates, batch processing, and advanced state management patterns for multi-page applications.
本文重点介绍了通过
gradio.Server将自定义前端与 Gradio 后端配对的核心功能。未来的更新将深入探讨使用@app.mcp.tool()进行 MCP 工具注册、用于实时更新的 SSE 流式传输、批处理以及针对多页应用的高级状态管理模式。
Recommended Reading
推荐阅读